; ** por compatibilidad se omiten tildes **
; ==============================================================================
; TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
; ==============================================================================
; definicion de rutinas de atencion de interrupciones

BITS 32

%include "macrosmodoprotegido.mac"

%define SET_PAGE         286
%define GET_CODE_STACK   386
%define fondoNegro 0x00
%define fondoVerde 0x20
%define fondoRojo 0x40
%define fondoAzul 0x10
%define fondoFucsia 0x50
%define fondoCeleste 0x30
%define fondo 0x78

extern fin_intr_pic1
extern proximo_indice
extern correrIdle
extern setPage
extern identificarTarea
extern eliminar_tarea
extern posicionCodigo
extern posicionStack

extern imprimir_registros
extern imprimir_tarea

extern dibujar_codigo
extern dibujar_stack
extern dibujar_shared
extern limpiar_codigo
extern limpiar_stack
extern limpiar_shared

global _isr0
global _isr1
global _isr2
global _isr3
global _isr4
global _isr5
global _isr6
global _isr7
global _isr8
global _isr9
global _isr10
global _isr11
global _isr12
global _isr13
global _isr14
global _isr15
global _isr16
global _isr17
global _isr18
global _isr19

global _isr32
global _isr33
global _isr69

; definicion de las rutinas de atencion de interrupciones
; Largo de los mensajes: 31 caracteres, 
isr69mensaje: db 'Parametros incorrectos         '
isr0mensaje:  db 'Divide by Zero                 '
isr1mensaje:  db 'Reserved for Intel use only    '
isr2mensaje:  db 'Nonmaskable External Interrupt '
isr3mensaje:  db 'Breakpoint                     '
isr4mensaje:  db 'Overflow                       '
isr5mensaje:  db 'Bound Range Exceeded           '
isr6mensaje:  db 'Invalid Opcode                 '
isr7mensaje:  db 'No Math Coprocessor            '
isr8mensaje:  db 'Double Fault                   '
isr9mensaje:  db 'Coprocessor Segment Overrun    '
isr10mensaje: db 'Invalid TSS                    '
isr11mensaje: db 'Segment Not Present            '
isr12mensaje: db 'Stack Segment Fault            '
isr13mensaje: db 'General Protection Fault       '
isr14mensaje: db 'Page Fault                     '
isr15mensaje: db 'Reserved for Intel use only    '
isr16mensaje: db 'x87 FPU Floating-Point Error   '
isr17mensaje: db 'Alignment Check                '
isr18mensaje: db 'Machine Check                  '
isr19mensaje: db 'SIMD Floating-Point Exception  ' 

%define color 0x2F

proximaTarea_offset: dd 0	;Offset del selector de la TSS de tarea inicial
proximaTarea_selector: dw 0	;Selector de la TSS de tarea idle

offset: dd 0	;Offset del selector de la TSS 
selector: dw 0	;Selector de la TSS de tarea

_isr0:
cli
	pushad
	call imprimir_registros
	mov edx, isr0mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 0
	push eax
	call imprimir_tarea
	add esp, 4
	popad

	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr1:
cli
	pushad
	call imprimir_registros
	mov edx, isr1mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 1
	push eax
	call imprimir_tarea
	add esp, 4
	popad

	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti
	jmp $

_isr2:
cli
	pushad
	call imprimir_registros
	mov edx, isr2mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 2
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr3:
cli
	pushad
	call imprimir_registros
	mov edx, isr3mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 3
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr4:
cli
	pushad
	call imprimir_registros
	mov edx, isr4mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 4
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr5:
cli
	pushad
	call imprimir_registros
	mov edx, isr5mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 5
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr6:
cli
	pushad
	call imprimir_registros
	mov edx, isr6mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 6
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr7:
cli
	pushad
	call imprimir_registros
	mov edx, isr7mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 7
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr8:
cli
	pushad
	call imprimir_registros
	mov edx, isr8mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 8
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr9:
cli
	pushad
	call imprimir_registros
	mov edx, isr9mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 9
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr10:
cli
	pushad
	call imprimir_registros
	mov edx, isr10mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 10
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr11:
cli
	pushad
	call imprimir_registros
	mov edx, isr11mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 11
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr12:
cli
	pushad
	call imprimir_registros
	mov edx, isr12mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 12
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr13:
cli
	pushad
	call imprimir_registros
	mov edx, isr13mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 13
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr14:
cli
	pushad
	call imprimir_registros
	mov edx, isr14mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 14
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr15:
cli
	pushad
	call imprimir_registros
	mov edx, isr15mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 15
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr16:
cli
	pushad
	call imprimir_registros
	mov edx, isr16mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 16
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti
	jmp $

_isr17:
cli
	pushad
	call imprimir_registros
	mov edx, isr17mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 17
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr18:
cli
	pushad
	call imprimir_registros
	mov edx, isr18mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 18
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $

_isr19:
cli
	pushad
	call imprimir_registros
	mov edx, isr19mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 19
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $
	
_isr69Error:
cli
	pushad
	call imprimir_registros
	mov edx, isr69mensaje
	IMPRIMIR_TEXTO edx, 31, color, 2, 43
	popad
	
	pushad
	mov eax, 69
	push eax
	call imprimir_tarea
	add esp, 4
	popad
	
	pushad
	mov eax, cr3
	push eax
	call eliminar_tarea
	add esp,4
	popad
	
	pushad
	call limpiar_codigo
	popad
	pushad
	call limpiar_stack
	popad
	pushad
	call limpiar_shared
	popad
	
	pushad
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	jmp far [TSSIDLE_offset]
	popad
sti	
	jmp $


TSSIDLE_offset: dd 0	;Offset del selector de la TSS de tarea inicial
TSSIDLE_selector: dw 0	;Selector de la TSS de tarea idle
; rutina de RELOJ
_isr32:
	cli 				;Deshabilitamos las interrupciones
	pushad				;Preservamos los registros
	call proximo_reloj	;Llamamos a la funcion proximo_reloj
	popad
	
	pushad
	call reloj_tarea
	popad
	
	pushad
	;Verificamos si esta pausado	
	mov eax, [isrPausa]
	cmp eax, 0x0
	je .seguir	;si no esta pausado, seguimos normal. si esta pausado, vamos a idle.	
	
	mov eax, [estaPausada]
	cmp eax, 0x0
	je .estabamosEnIdle
.noCambiar:
	call fin_intr_pic1	;Comunicamos al PIC que ya se atendió la interrupcion	
	jmp .fin32 ;ya esta pausada, no volvemos a saltar al mismo lugar porque se rompe todo

.estabamosEnIdle:
	mov eax, cr3
	push eax
	call identificarTarea
	add esp, 4
	cmp eax, 1
	jl .noCambiar
	cmp eax, 5
	jg .noCambiar
	jmp .irAIdle ;no estabamos en Idle, podemos cambiar a Idle sin problemas.
	
.irAIdle:
	mov DWORD [estaPausada], 0x1
	mov eax, 2	;Indice de la tarea Idle = 2
	shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [TSSIDLE_selector], ax
	call fin_intr_pic1	;Comunicamos al PIC que ya se atendió la interrupcion	
	jmp far [TSSIDLE_offset]
	jmp .fin32
	
.seguir:
	call dibujar_codigo
	popad
	pushad
	call dibujar_stack
	popad
	pushad
	call dibujar_shared ;antes de pasar a la proxima tarea actualizamos en pantalla la arena
	popad
	
	mov DWORD [estaPausada], 0x0
	
	pushad
	call proximo_indice	;Llamamos a la funcion proximo_indice
	
	cmp ax, 0
	je .nojump
		shl eax, 3			;Multiplicamos por 8 para obtener el indice
		add eax, 3			;Sumamos para setear el RPL de nivel 3
		mov [selector], ax
		call fin_intr_pic1	;Comunicamos al PIC que ya se atendió la interrupcion	
		jmp far [offset]
		jmp .fin32
	
.nojump:	
	call fin_intr_pic1	;Comunicamos al PIC que ya se atendió la interrupcion	

.fin32:	
	popad				;Restauramos los registros
	sti					;Habilitamos las interrupciones
	iret				;Retornamos de la interrupcion
	
; rutina de TECLADO
_isr33:
	cli					;Deshabilitamos las interrupciones
	pushad				;Preservamos los registros
	call fin_intr_pic1	;Comunicamos al PIC que ya se atendió la interrupcion		
	
	xor eax, eax
	call numeroTeclado	;Escribimos el numero por pantalla
		
	popad				;Restauramos los registros
	sti					;Habilitamos las interrupciones
	iret				;Retornamos de la interrupcion

; rutina de SERVICIOS
_isr69:
	cli					;Deshabilitamos las interrupciones
	
	cmp eax, 286		;Nos fijamos si es set_page
	je .setPage
	cmp eax, 386		;Nos fijamos si es get_code_stack
	je .getCodeStack
	
	;sti
	jmp _isr69Error			;Mostramos mensaje de error
	
.setPage:
	pushad				;Preservamos los registros
	call limpiar_shared	;antes de cambiar el shared limpiamos donde estaba antes
	popad
	
	pushad
	mov eax, cr3
	push eax
	push ebx
	call setPage		;hacemos el setpage
	add esp, 8
	popad
	
	pushad
	call dibujar_codigo
	popad
	pushad
	call dibujar_stack
	popad
	pushad
	call dibujar_shared ;antes de pasar a la proxima tarea actualizamos en pantalla la arena
	popad
	
	pushad
	call reloj_tarea
	popad
	
	pushad
	;Saltamos a la tarea idle
	mov eax, 2	;Indice de la tarea Idle
	shl eax, 3	;Como ebx tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
	mov [proximaTarea_selector], ax
	jmp far [proximaTarea_offset] ;le decimos al scheduler que corra la tarea idle
	popad				;Restauramos los registros
	
	jmp .fin69
	
.getCodeStack:
	push eax	;preservamos eax
	mov eax, cr3
	push eax
	call posicionCodigo
	add esp, 4
	mov ecx, eax
	mov eax, cr3
	push eax
	call posicionStack
	add esp, 4
	mov edx, eax
	pop eax		;restauramos eax
	jmp .fin69
	
.fin69:
	sti				;Habilitamos las interrupciones
	iret				;Retornamos de la interrupcion

; rutina del reloj
proximo_reloj:
	pushad
	inc DWORD [isrnumero]
	mov ebx, [isrnumero]
	cmp ebx, 0x4
	jl .ok
		mov DWORD [isrnumero], 0x0
		mov ebx, 0
	.ok:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, 0x0f, 24, 79
	popad
	ret
	
isrnumero: dd 0x00000000
isrClock:  db '|/-\'
isrPausa:  dd 0x0000
estaPausada:  dd 0x0000

; rutina del teclado para escribir numeros
numeroTeclado:
	pushad
	xor eax, eax
	in al, 0x60		;Leemos el teclado a través del puerto 0x60, tenemos en al el scan code
	test al, 0x80	;Vemos si es makecode o breakcode
	je .es_makecode
	
	;es Breakcode
	xor eax, eax
	add eax, isrVacio
	IMPRIMIR_TEXTO eax, 1, 0x00, 0, 79	;Imprimimos el cuadrado negro como estaba antes
	jmp .fin
	
.es_makecode:
	cmp al, 0x02
	jl .fin				;si es escape o error salimos
	cmp al, 0x0b
	jg .pausa			;si es mayor no corresponde a un numero
	dec al
	dec al				;restamos dos para que quede mapeado con nuestro string
	add eax, isrKeyboard
	IMPRIMIR_TEXTO eax, 1, 0x0F, 0, 79
	jmp .fin
	
.pausa:
	cmp al, 0x19 ;vemos si es la P
	jne .reinicio
	mov DWORD [isrPausa], 0x1
	jmp .fin
	
.reinicio:
	cmp al, 0x13 ;vemos si es la R
	jne .fin
	mov DWORD [isrPausa], 0x0
	jmp .fin
		
.fin:
	popad
	ret
	
isrKeyboard:  db '1234567890'
isrVacio:  db ' '

reloj_tarea:
	pushad
	mov eax, cr3
	push eax
	call identificarTarea	;resultado en eax
	add esp, 4
	
	cmp eax,1
	jne .tarea2
	inc DWORD [isrnumero1]
	mov ebx, [isrnumero1]
	cmp ebx, 0x4
	jl .ok1
		mov DWORD [isrnumero1], 0x0
		mov ebx, 0
	.ok1:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, fondoVerde, 19, 0
	jmp .fin

.tarea2:
	cmp eax,2
	jne .tarea3
	inc DWORD [isrnumero2]
	mov ebx, [isrnumero2]
	cmp ebx, 0x4
	jl .ok2
		mov DWORD [isrnumero2], 0x0
		mov ebx, 0
	.ok2:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, fondoRojo, 20, 0
	jmp .fin
	
.tarea3:
	cmp eax,3
	jne .tarea4
	inc DWORD [isrnumero3]
	mov ebx, [isrnumero3]
	cmp ebx, 0x4
	jl .ok3
		mov DWORD [isrnumero3], 0x0
		mov ebx, 0
	.ok3:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, fondoCeleste, 21, 0
	jmp .fin
	
.tarea4:
	cmp eax,4
	jne .tarea5
	inc DWORD [isrnumero4]
	mov ebx, [isrnumero4]
	cmp ebx, 0x4
	jl .ok4
		mov DWORD [isrnumero4], 0x0
		mov ebx, 0
	.ok4:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, fondoAzul, 22, 0
	jmp .fin
	
.tarea5:
	cmp eax,5
	jne .fin
	inc DWORD [isrnumero5]
	mov ebx, [isrnumero5]
	cmp ebx, 0x4
	jl .ok5
		mov DWORD [isrnumero5], 0x0
		mov ebx, 0
	.ok5:
		add ebx, isrClock
		IMPRIMIR_TEXTO ebx, 1, fondoFucsia, 23, 0
	jmp .fin
	
.fin:	
	popad
	ret
	
isrnumero1: dd 0x00000000
isrnumero2: dd 0x00000000
isrnumero3: dd 0x00000000
isrnumero4: dd 0x00000000
isrnumero5: dd 0x00000000
